#ifndef __EKOS_KERNEL_PROC_H__
#define __EKOS_KERNEL_PROC_H__

#define PROC_KSTACK_TOP(_pid) (KSTACK + ((_pid + 1) << KSTACK_SHIFT))

extern volatile struct proc_t *procs;
/* The big lock of global proc allocation/free operation */
extern mcs_lock_t proc_alloc_lock;
extern volatile proc_id_t proc_free_head;

struct env_t
{
	 union
	 {
		  struct
		  {
		  	   spin_lock_t lock;
		  	   int instance_count;
		  };

		  proc_id_t free_next;
	 };
};

extern volatile struct env_t envs[PROCESS_MAX_COUNT];
extern mcs_lock_t env_alloc_lock;
extern volatile proc_id_t env_free_head;

proc_id_t env_alloc(void);
void env_free(proc_id_t id);

/* The scheduler interface */
struct scheduler_t
{
	 /* point to the implement-accociated data */
	 void *data;
	 /* get the next ready env idx, args: data, hint */
	 int (*do_schedule)(void *, proc_id_t cur, int hint);
	 int (*wait)(void *, proc_id_t pid);
	 int (*notify)(void *, proc_id_t pid);
};

/* hint -- called by time interrupt */
#define SCH_HINT_PERIOD 0
/* hint -- called by user that really want to be switched out */
#define SCH_HINT_FORCE  1

physaddr_t do_schedule(uint32_t *esp, uint32_t *eflags, int hint);
int sch_wait(proc_id_t pid, int plock, spin_lock_t *lock);
int sch_notify(proc_id_t pid, int plock);

int proc_set_priority(int priority);
int proc_set_signal_handler(uintptr_t handler);
int proc_set_signal_flags(uint16_t flags, uint16_t sch_count);

/* The proc management */
void fork_proc(struct trapframe_t *tf);

#endif
